package com.fhao.aop.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Slf4j //日志打印
//@Component //将类对象交给spring管理
@Aspect //该注解表明了该类是一个切面类. Spring使用了Aspectj的注解,具体实现是Spring实现的,不是这个注解实现的,Aspectj是一个第三方的iar包.
public class AspectDemo {
    //描述一个切点的注解
    @Pointcut("execution(* com.fhao.aop.controller.*.*(..))")
    public void pt(){};
    /**
     * 前置通知
     */
//    @Before("execution(* com.fhao.aop.controller.*.*(..))") //切点: 规则的适用范围(作用范围)
    @Before("pt()")
    public void doBefore() { //连接点: 方法
        log.info("AspectDemo do before....");
    }

    /**
     * 后置通知
     */
//    @After("execution(* com.fhao.aop.controller.*.*(..))")
    @After("pt()")
    public void doAfter() {
        log.info("AspectDemo do after....");
    }

    /**
     * 环绕通知
     * @param joinPoint
     * @return
     * @throws Throwable
     */
//    @Around("execution(* com.fhao.aop.controller.*.*(..))")
    @Around("pt()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable { //必须要有返回结果.
        log.info("AspectDemo do Around before...."); //优先级高于 Before
        Object result = null;
        try {
            result = joinPoint.proceed();
        }catch (Exception e) {
            log.error("do around执行目标函数,内部发生异常");
        }
        log.info("AspectDemo do Around After"); //优先级低于 After
        return result;
    }

    /**
     * 返回后通知,目标方法执行完之后执行,有异常则不会执行
     */
//    @AfterReturning("execution(* com.fhao.aop.controller.*.*(..))")
    @AfterReturning("pt()")
    public void doAfterReturning() {
        log.info("AspectDemo do after returning....");
    }

    /**
     * 返回后通知,目标方法执行时有异常则执行,否则不会执行.
     */
//    @AfterThrowing("execution(* com.fhao.aop.controller.*.*(..))")
    @AfterThrowing("pt()")
    public void doAfterThrowing() {
        log.info("AspectDemo do after throwing....");
    }
}










